﻿namespace Microsoft.SharePoint.Client
{
    using System;
    using System.Collections.Generic;

    public sealed class ExceptionHandlingScope : IFromJson
    {
        private ExecutionScope m_catchScope;
        private ClientRuntimeContext m_context;
        private string m_errorMessage;
        private ExecutionScope m_executionScope;
        private ExecutionScope m_finallyScope;
        private bool m_hasError;
        private bool m_processed;
        private int m_serverErrorCode;
        private string m_serverErrorValue;
        private string m_serverStackTrace;
        private ExecutionScope m_tryScope;

        public ExceptionHandlingScope(ClientRuntimeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            this.m_context = context;
            this.m_serverErrorCode = -1;
        }

        internal static Exception CreateInvalidUsageException()
        {
            return new ClientRequestException(Resources.GetString("InvalidUsageOfExceptionHandlingScope"));
        }

        private void ExceptionHandlingScopeDisposingCallback()
        {
            if (this.m_tryScope != null)
            {
                if ((this.m_catchScope == null) && (this.m_finallyScope == null))
                {
                    throw CreateInvalidUsageException();
                }
                ClientAction lastAction = this.m_context.PendingRequest.LastAction;
                if ((lastAction == null) || !(lastAction is ClientActionExecutionScopeEnd))
                {
                    throw CreateInvalidUsageException();
                }
                ClientActionExecutionScopeEnd end = (ClientActionExecutionScopeEnd) lastAction;
                if ((end.Scope.Name != "CatchScope") && (end.Scope.Name != "FinallyScope"))
                {
                    throw CreateInvalidUsageException();
                }
            }
        }

        bool IFromJson.CustomFromJson(JsonReader reader)
        {
            return false;
        }

        void IFromJson.FromJson(JsonReader reader)
        {
            object obj2 = reader.ReadObject();
            Dictionary<string, object> dictionary = obj2 as Dictionary<string, object>;
            if (dictionary == null)
            {
                throw new ClientRequestException(Resources.GetString("UnknownResponseData"));
            }
            if (!dictionary.TryGetValue("HasException", out obj2))
            {
                throw new ClientRequestException(Resources.GetString("UnknownResponseData"));
            }
            this.m_hasError = (bool) obj2;
            if (this.m_hasError)
            {
                if (!dictionary.TryGetValue("ErrorInfo", out obj2))
                {
                    throw new ClientRequestException(Resources.GetString("UnknownResponseData"));
                }
                Dictionary<string, object> errorInfo = obj2 as Dictionary<string, object>;
                if (errorInfo == null)
                {
                    throw new ClientRequestException(Resources.GetString("UnknownResponseData"));
                }
                ServerException exception = ServerException.CreateFromErrorInfo(errorInfo);
                this.m_errorMessage = exception.Message;
                this.m_serverStackTrace = exception.ServerStackTrace;
                this.m_serverErrorCode = exception.ServerErrorCode;
                this.m_serverErrorValue = exception.ServerErrorValue;
            }
            this.m_processed = true;
        }

        public IDisposable StartCatch()
        {
            if ((((this.m_executionScope == null) || this.m_executionScope.Disposed) || ((this.m_tryScope == null) || !this.m_tryScope.Disposed)) || ((this.m_catchScope != null) || (this.m_finallyScope != null)))
            {
                throw CreateInvalidUsageException();
            }
            ClientAction lastAction = this.m_context.PendingRequest.LastAction;
            if ((lastAction == null) || !(lastAction is ClientActionExecutionScopeEnd))
            {
                throw CreateInvalidUsageException();
            }
            if (((ClientActionExecutionScopeEnd) lastAction).Scope.Name != "TryScope")
            {
                throw CreateInvalidUsageException();
            }
            this.m_catchScope = new ExecutionScope(this.m_context, "CatchScope", null);
            return this.m_catchScope;
        }

        public IDisposable StartFinally()
        {
            if (((((this.m_executionScope == null) || this.m_executionScope.Disposed) || ((this.m_tryScope == null) || !this.m_tryScope.Disposed)) || ((this.m_catchScope != null) && !this.m_catchScope.Disposed)) || (this.m_finallyScope != null))
            {
                throw CreateInvalidUsageException();
            }
            ClientAction lastAction = this.m_context.PendingRequest.LastAction;
            if ((lastAction == null) || !(lastAction is ClientActionExecutionScopeEnd))
            {
                throw CreateInvalidUsageException();
            }
            if ((((ClientActionExecutionScopeEnd) lastAction).Scope.Name != "TryScope") && (((ClientActionExecutionScopeEnd) lastAction).Scope.Name != "CatchScope"))
            {
                throw CreateInvalidUsageException();
            }
            this.m_finallyScope = new ExecutionScope(this.m_context, "FinallyScope", null);
            return this.m_finallyScope;
        }

        public IDisposable StartScope()
        {
            if (this.m_executionScope != null)
            {
                throw CreateInvalidUsageException();
            }
            this.m_executionScope = new ExceptionHandlingExecutionScope(this.m_context, this, new ExecutionScopeDisposingCallback(this.ExceptionHandlingScopeDisposingCallback));
            this.m_context.PendingRequest.AddQueryIdAndResultObject(this.m_executionScope.Id, this);
            return this.m_executionScope;
        }

        public IDisposable StartTry()
        {
            if (((this.m_executionScope == null) || this.m_executionScope.Disposed) || (this.m_tryScope != null))
            {
                throw CreateInvalidUsageException();
            }
            ClientAction lastAction = this.m_context.PendingRequest.LastAction;
            if ((lastAction == null) || !(lastAction is ClientActionExecutionScopeStart))
            {
                throw CreateInvalidUsageException();
            }
            if (((ClientActionExecutionScopeStart) lastAction).Scope.Name != "ExceptionHandlingScope")
            {
                throw CreateInvalidUsageException();
            }
            this.m_tryScope = new ExecutionScope(this.m_context, "TryScope", null);
            return this.m_tryScope;
        }

        public string ErrorMessage
        {
            get
            {
                return this.m_errorMessage;
            }
        }

        public bool HasException
        {
            get
            {
                return this.m_hasError;
            }
        }

        internal bool IsSimpleForm
        {
            get
            {
                return (this.m_tryScope == null);
            }
        }

        public bool Processed
        {
            get
            {
                return this.m_processed;
            }
        }

        public int ServerErrorCode
        {
            get
            {
                return this.m_serverErrorCode;
            }
        }

        public string ServerErrorValue
        {
            get
            {
                return this.m_serverErrorValue;
            }
        }

        public string ServerStackTrace
        {
            get
            {
                return this.m_serverStackTrace;
            }
        }
    }
}

